<?php

/**
* internal library of functions and constants for Poodll modules
* accessed directly by poodll flash wdgets on web pages.
* @package mod-poodllpairwork
* @category mod
* @author Justin Hunt
*
*/


/**
* Includes and requires
*/
//ob_start();
global $CFG;

//we need to do this, because when called from a widet, cfg is not set
//but the relative path fails from a quiz but it has already been set in that case
//, so we check before we call it, to cover both bases

if(!$CFG){
require_once("../../config.php");
}
//require_once('../filter/poodll/poodllinit.php');
require_once($CFG->dirroot . "/filter/poodll/poodllinit.php");

//commented just while getting other mods working

//added for moodle 2
require_once($CFG->libdir . '/filelib.php');

	$datatype = optional_param('datatype', "", PARAM_TEXT);    // Type of action/data we are requesting
	$contextid  = optional_param('contextid', 0, PARAM_INT);  // the id of the course 
	$courseid  = optional_param('courseid', 0, PARAM_INT);  // the id of the course 
	$moduleid  = optional_param('moduleid', 0, PARAM_INT);  // the id of the module 
	$itemid  = optional_param('itemid', 0, PARAM_INT);  // the id of the module
	$hash  = optional_param('hash', "", PARAM_TEXT);  // file or dir hash
	$requestid  = optional_param('requestid', "", PARAM_TEXT);  // file or dir hash
	$paramone  = optional_param('paramone', "", PARAM_TEXT);  // nature of value depends on datatype, maybe path
	$paramtwo  = optional_param('paramtwo', "", PARAM_TEXT);  // nature of value depends on datatype, maybe protocol
	$paramthree  = optional_param('paramthree', "", PARAM_TEXT);  // nature of value depends on datatype, maybe filearea

	switch($datatype){
		
		case "poodllpluginfile":
			//poodllpluginfile($contextid,$component,$filearea,$itemid,$filepath,$filename);
			//lets hard code this for now, very very mild security
			poodllpluginfile($contextid,"mod_assignment","submission",$itemid,"/",$paramone);
			return;
	
		case "getlast20files":
			header("Content-type: text/html");
			$returnxml="";
			echo "hi";
			getLast20Files();
			break;
	
		case "getrepodata": 
			header("Content-type: text/xml");
			echo "<?xml version=\"1.0\"?>\n";
			$returnxml=fetch_repos();
			break;

		case "repodirlist": 
			header("Content-type: text/xml");
			echo "<?xml version=\"1.0\"?>\n";
			$returnxml=fetch_repodirlist($paramone);
			break;	
			
		case "instancedirlist": 
			header("Content-type: text/xml");
			echo "<?xml version=\"1.0\"?>\n";
			//paramone=path, paramtwo=filearea
			$returnxml=fetch_instancedirlist($moduleid, $courseid, $itemid, $paramone, $paramtwo);
			break;
				
		case "legacydirlist": 
			header("Content-type: text/xml");
			echo "<?xml version=\"1.0\"?>\n";
			//paramone=path, paramtwo=filearea
			$returnxml=fetch_legacydirlist($courseid);
			break;
				
		case "instancedeleteall": 
			header("Content-type: text/xml");
			echo "<?xml version=\"1.0\"?>\n";
			$returnxml=instance_deleteall($moduleid, $courseid, $itemid, $paramone, $requestid);
			break;
			
		case "instancecopyfile": 
			header("Content-type: text/xml");
			echo "<?xml version=\"1.0\"?>\n";
			//$moduleid, $courseid, $itemid, $filearea, $filepath,$newpath, $requestid)
			$returnxml=instance_copyfilein($moduleid, $courseid,$itemid, $paramone, $paramtwo, $paramthree, $requestid);
			break;
			
		case "instanceduplicatefile": 
			header("Content-type: text/xml");
			echo "<?xml version=\"1.0\"?>\n";
			//module, course, itemid, filearea, filepath, (origfile)hash,  reqid
			$returnxml=instance_duplicatefile($moduleid, $courseid, $itemid, $paramone,  $paramtwo, $hash, $requestid);
			break;
		
		case "instancedeletefile": 
			header("Content-type: text/xml");
			echo "<?xml version=\"1.0\"?>\n";
			$returnxml=instance_deletefile($hash, $requestid);
			break;
			
		case "instancefetchfileinfo": 
			header("Content-type: text/xml");
			echo "<?xml version=\"1.0\"?>\n";
			$returnxml=instance_fetchfileinfo($hash, $requestid);
			break;
			
		case "instancecreatedir": 
			header("Content-type: text/xml");
			echo "<?xml version=\"1.0\"?>\n";
			$returnxml=instance_createdir($moduleid, $courseid, $itemid, $paramone, $paramtwo, $requestid);
			break;

		case "instancecopydir": 
			header("Content-type: text/xml");
			echo "<?xml version=\"1.0\"?>\n";
			$returnxml=instance_copydirin($moduleid, $courseid, $itemid, $paramone, $paramtwo, $paramthree, $requestid);
			break;
		
		
		case "instancerenamefile": 
			header("Content-type: text/xml");
			echo "<?xml version=\"1.0\"?>\n";
			//module, course, originalhash, newfilename, copyas, reqid
			$returnxml=instance_renamefile($moduleid, $courseid, $hash, $paramone, false, $requestid);
			break;
			
		case "instancecopyasfile": 
			header("Content-type: text/xml");
			echo "<?xml version=\"1.0\"?>\n";
			//module, course, originalhash, newfilename, copyas, reqid
			$returnxml=instance_renamefile($moduleid, $courseid, $hash, $paramone, true, $requestid);
			break;
			
		case "getmoddata": 
			header("Content-type: text/xml");
			echo "<?xml version=\"1.0\"?>\n";
			$returnxml=getmoddata($courseid, $requestid);
			break;	
		
		case "fetchrealurl": 
			header("Content-type: text/xml");
			echo "<?xml version=\"1.0\"?>\n";
			$returnxml=fetchrealurl($moduleid,$courseid, $itemid, $paramone, $paramtwo, $requestid);
			break;
			
		case "instancedownload":
			//paramone=mimetype paramtwo=path paramthree=hash
			instance_download($paramone,$paramtwo,$hash,$requestid);
			
		case "instanceremotedownload":
			//($contextid,$filename,$component, $filearea,$itemid, $requestid)
			//e.g (15, '123456789.flv','user','draft','746337947',777777)
			$returnxml=instance_remotedownload($contextid, $paramone,$paramtwo,$paramthree,$itemid,$requestid);
			
			//move the output to here so that there is no trace of stray characters entering output before file downloaded
			header("Content-type: text/xml");
			echo "<?xml version=\"1.0\"?>";
			
			//$returnxml="<hello />";
			//instance_remotedownload('930884190835059.flv','user','draft',746337947);
			break;			

		default:
			return;
			/*
			header("Content-type: text/xml");
			echo "<?xml version=\"1.0\"?>\n";
			$returnxml="";
			break;	
		*/

	}


	echo $returnxml;
	return;




//Fetch a sub directory list for file explorer  
//calls itself recursively, dangerous
function fetch_repodircontents($dir,  $recursive=false){
	$xml_output="";
	$files = scandir($dir);
	if (!empty($files)) {
        foreach ($files as $afile) {
			if ($afile == "." || $afile == "..") {
				continue;
			}
			//here we encode the filename 
			//because the xml breaks otherwise when there arequotes etc.
			$escapedafile =  htmlspecialchars( $afile,ENT_QUOTES);
			if(is_dir($dir."/".$afile)){
				if(!$recursive){
					$xml_output .=  "\t<directory name='" . $escapedafile . "' />\n";
				}else{				
					//recursive
					$xml_output .=  "\t<directory name='" . $escapedafile . "' >\n";
					$xml_output .= fetch_repodircontents($dir."/".$afile,true);	
					$xml_output .=  "\t</directory>";
				}				
			}else{
				$xml_output .=  "\t<file name='" . $escapedafile ."' isleaf='true' "  
				. " filesize='" . filesize($dir . "/" . $afile)  
				. "' created='" . date('d M Y H:i:s', filectime($dir . "/" . $afile)) 
				. "' modified='" . date('d M Y H:i:s', filemtime($dir . "/" . $afile)) 
				. "' type='" .  htmlspecialchars(mime_content_type ($dir . "/" . $afile),ENT_QUOTES)  
				. "'/>\n";
				
				
				
				
				
			}
		}
	}
	return $xml_output;
}



//Fetch a directory list from the repo
function fetch_repodirlist($startpath=''){
	global $CFG;	
	
	
	global $basedir;
    global $usecheckboxes;
    global $id;
    global $USER, $CFG;
	
	//Handle directories
	$fullpath = $CFG->{'dataroot'}  . "/repository/" . $startpath;
	
	//open xml to return
	$xml_output = "<directorylist>";
	
	
	
	/* New way which works with php5, but not is_dir : Justin */
	$files = scandir($fullpath);
	if (!empty($files)) {
		$xml_output .= fetch_repodircontents($fullpath,true);
	}
	
	
	
	//close xml to return
	$xml_output .= "</directorylist>";
	
	//Return the data
	return $xml_output;
	
	
}


//Fetch a directory list from the repo
function fetch_repos(){
	global $CFG, $DB;	
	
	
	global $basedir;
    global $usecheckboxes;
    global $id;
    global $USER, $CFG;
	
	//Handle directories
	$fullpath = $CFG->{'dataroot'}  . DIRECTORY_SEPARATOR . "repository";
	
	//open xml to return
	$xml_output = "<repositories>";
	
	
	
	
	/// USe this to extract only unique file paths that can be tacked on  / add ri.contextid to hone down the permissions level
	$sql = "SELECT DISTINCT(ric.value) as filepath FROM {repository} r , {repository_instances} ri , {repository_instance_config} ric  WHERE r.type='filesystem' AND ric.name='fs_path' AND r.id=ri.typeid  AND ri.id=ric.instanceid" ;

	 //or try this if above dont work
   	//$sql = "SELECT DISTINCT(ric.value) as filepath FROM {repository} r JOIN {repository_instances} ri ON r.id=ri.typeid JOIN {repository_instance_config} ric ON ri.id=ric.instanceid WHERE r.type='filesystem' AND ric.name='fs_path'";
  
   //possibly could be shortened to 
   //$sql = "SELECT UNIQUE(ric.value) as filepath FROM {repository_instance_config} ric WHERE  ric.name='fs_path'";

   $records=$DB->get_records_sql($sql);
   if (!empty($records)) {
		
		foreach ($records as $record){
			$adir=  htmlspecialchars( $record->filepath,ENT_QUOTES);
			if(is_dir($fullpath . DIRECTORY_SEPARATOR .  $adir)){
				if($adir != "." && $adir != ".."){
					$xml_output .="<repo name='" . $adir . "' path='" . $fullpath . DIRECTORY_SEPARATOR .  $adir . "'/>";
				}
			}
		}
		
	}
	
	

/* This way just got all the sub directories of repository
	$files = scandir($fullpath);
	if (!empty($files)) {
		
		foreach ($files as $afile){
			$afile =  htmlspecialchars( $afile,ENT_QUOTES);
			if(is_dir($fullpath . DIRECTORY_SEPARATOR .  $afile)){
				if($afile != "." && $afile != ".."){
					$xml_output .="<repo name='" . $afile . "' path='" . $fullpath . DIRECTORY_SEPARATOR .  $afile . "'/>";
				}
			}
		}
		
	}
	*/
	
	//close xml to return
	$xml_output .= "</repositories>";
	
	//Return the data
	return $xml_output;
	
	
}



//This will fetch the contents of a module instance directory, can be recursively called
function fetch_instancedir_contents($thedir, &$thecontext, $recursive=false){
	
	$browser = get_file_browser();
	$xml_output="";
	
	//first process subdirectories (if recursive)
	if(!empty($thedir['subdirs']) && $recursive){
	
		usort($thedir['subdirs'], "compareDirnames");
		
		 foreach ($thedir['subdirs'] as $subdir) {
			 //this is only necessary of you deleted the dirfile without deleting the subfiles
			 //ie only a dev, not real world situation
			 if(!array_key_exists('dirfile',$subdir)){return;}
			$f = $subdir['dirfile'];
			//$filename =$f->get_filename();
			$filename=poodllBasename($f->get_filepath());
			//$filename=basename($f->get_filepath(),"/");
			/*
			if ($filename == "." || $filename == "..") {
				continue;
			}
			*/
			
			
					
			//fetch our info object
			$fileinfo = $browser->get_file_info($thecontext, $f->get_component(),$f->get_filearea(), $f->get_itemid(), $f->get_filepath(), $f->get_filename());
			
				//If we could get an info object, process. But if we couldn't, although we have info via $f, we don't have permissions
				//so we don't reveal it
				if($fileinfo){
					$urltofile = $fileinfo->get_url();
				/* if(true){
					if(!$fileinfo){
							$urltofile="denied";
						}else{
							$urltofile = $fileinfo->get_url();
						}
			
					*/
					
					//filehash for any delete/edit manipulations we wish to do
					$hash= $f->get_pathnamehash();	
				
					//output xml for dir (escape for odd quotes that kill xml parser)
					$xml_output .=  "\t<directory name='" . htmlspecialchars($filename,ENT_QUOTES) ."'  url='" . htmlspecialchars($urltofile,ENT_QUOTES) . "' hash='" . $hash . "'>\n";
					$xml_output .= fetch_instancedir_contents($subdir,$thecontext,true);	
					$xml_output .=  "\t</directory>";
			
				//}else{
				//	$xml_output .= "<directory url='booboo' name='" . $thecontext->id .'@'. $f->get_component() .'@'. $f->get_filearea() .'@'. $f->get_itemid() .'@'. $f->get_filepath() .'@'. $f->get_filename() . "' hash='buubuu' />";
				}
		
	
		}
		
	}
	
	//then process files
	$files = $thedir['files'];
	if (!empty($files)) {
		usort($files, "compareFilenames");
			foreach ($files as $f) {
				$filename =$f->get_filename();
				if ($filename == "." || $filename == "..") {
					continue;
				}
		
				//fetch our info object
				$fileinfo = $browser->get_file_info($thecontext, $f->get_component(),$f->get_filearea(), $f->get_itemid(), $f->get_filepath(), $f->get_filename());

				
				//get the url to the file
				if($fileinfo){
					$urltofile = $fileinfo->get_url();
			/*	 if(true){
					if(!$fileinfo){
							$urltofile="denied";
						}else{
							$urltofile = $fileinfo->get_url();
						}
						*/
						
					
					//filehash for any delete/edit manipulations we wish to do
					$hash= $f->get_pathnamehash();
					
					//create the output xml for this file/dir, we escape special characters so as not to break XML parsing
					$xml_output .=  "\t<file name='" . htmlspecialchars($filename,ENT_QUOTES) ."' isleaf='true' url='" . 
						htmlspecialchars($urltofile,ENT_QUOTES)  . "' filesize='" . $f->get_filesize()  
						. "' created='" . date('d M Y H:i:s', $f->get_timecreated())  
						. "' modified='" . date('d M Y H:i:s', $f->get_timemodified()) 
						. "' type='" . $f->get_mimetype() 
						. "' hash='" . $hash . "'/>\n";

				}//end of if($fileinfo)
				
		}//end of for each
	
	}//end of if empty
	
	return $xml_output;

}

//This is just so we can get a list of stuff in the old course legacy files area
//we can try if it works but it might not.
function fetch_legacydirlist($courseid){

$thiscontext = get_context_instance(CONTEXT_COURSE, $courseid);
$contextid = $thiscontext->id;
    
    $fs = get_file_storage();
  
  
  //set up xml to return	
	$xml_output = "<directorylist>\n";
  
   $fullpath = "/$contextid/course/legacy/0/";
   $file = $fs->get_file_by_hash(sha1($fullpath));
   
   if(!$file){
   	$fullpath = "/$contextid/course/legacy/0";
   	$file = $fs->get_file_by_hash(sha1($fullpath));
   }
   
   if ($file) {
   		//set up xml to return	
		//$xml_output .= "we have a file";
		$topdir = $fs->get_area_tree($file->get_contextid(), $file->get_component(), $file->get_filearea(),$file->get_itemid());
		$xml_output .= fetch_instancedir_contents($topdir,$thiscontext,true);
	}else{
		$xml_output .= "no files " . $courseid . " " . $contextid . " " . $fullpath;
	}
	

	//close xml to return
	$xml_output .= "</directorylist>";

	//Return the data
	return $xml_output;
	
}

//This will fetch the directory list of all the files
//available in a module instance (ie added from repository)
function fetch_instancedirlist($moduleid, $courseid, $itemid, $path, $filearea){
global $CFG, $DB;

	//FIlter could submit submission/draft/content/intro as options here
	if($filearea == "") {$filearea ="content";}
	
	//fetch info and ids about the module calling this data
	$course = $DB->get_record('course', array('id'=>$courseid));
	$modinfo = get_fast_modinfo($course);
	$cm = $modinfo->get_cm($moduleid);

	//get filehandling objects
	$browser = get_file_browser();
	$fs = get_file_storage();
	
	//set up xml to return	
	$xml_output = "<directorylist>\n";
	

	//get a handle on the module context
	$thiscontext = get_context_instance(CONTEXT_MODULE,$moduleid);
	$contextid = $thiscontext->id;
	
	//fetch a list of files in this area, and sort them alphabetically
	
	$topdir = $fs->get_area_tree($contextid, "mod_" . $cm->modname, $filearea,$itemid);
	$xml_output .= $cm->modname . " " . $itemid;
	//when dev/testing set the recursive flag to false if you prefer not to wait for infinite loops.
	$xml_output .= fetch_instancedir_contents($topdir,$thiscontext,true);
	
	//close xml to return
	$xml_output .= "</directorylist>";

	//Return the data
	return $xml_output;

}


//This will delete all files attached to a module instance
//this works but it should no really be used by joe user.
//commented because unsecure. Justin 20111103
/*
function instance_deleteall($moduleid, $courseid, $filearea, $requestid){
	global $CFG, $DB;

	//FIlter could submit submission/draft/content/intro as options here
	if($filearea == "") {$filearea ="content";}
	
	//fetch info and ids about the module calling this data
	$course = $DB->get_record('course', array('id'=>$courseid));
	$modinfo = get_fast_modinfo($course);
	$cm = $modinfo->get_cm($moduleid);
	$component = "mod_" . $cm->modname;
	
	//get a handle on the module context
	$thiscontext = get_context_instance(CONTEXT_MODULE,$moduleid);
	$contextid = $thiscontext->id;

	//get filehandling objects
	$browser = get_file_browser();
	$fs = get_file_storage();

	
	//set up xml to return	
	$xml_output = "<result requestid='" . $requestid . "'>\n";
	
	
	if($fs->delete_area_files($contextid, $component, $filearea, $itemid)){
		$xml_output .= "success";
	}else{
		$xml_output .= "failure";
	}
	
	$xml_output .= "</result>\n";	
	
	//Return the data
	return $xml_output;

}
*/

/*
* This function is a simple replacement for pluginfile.php when called from assignemnets
* There is whitespace, newline chars, added at present(20120306) so need to bypass
*
*/
function poodllpluginfile($contextid,$component,$filearea,$itemid,$filepath,$filename){
	
	$fs = get_file_storage();
	$br = get_file_browser();
	$f = $fs->get_file($contextid, $component, $filearea, $itemid, $filepath, $filename);
	
	//if no file we just quit.
	if(!$f){return;}
	
	//get permission info for this file: but it doesn't work oh no.....another moodle bug?
	/*
	$thecontext = get_context_instance_by_id($contextid);
	$fileinfo = $br->get_file_info($thecontext, $component,$filearea, $itemid, $filepath, $filename);	

	//if we don't have permission to read, exit
	if(!$fileinfo || !$fileinfo->is_readable()){echo "crap"; return;}
		*/
	
	//send_stored_file also works: but we are using send file, for no reason really
	//send_stored_file($f, 0, 0, true); // download MUST be forced - security!
	
	$fcontent = $f->get_content();
	send_file($fcontent, $filename, 0, 0, true, true, "video/x-flv");
	return;
}

/* download file from remote server and stash it in our file area */
//15,'123456789.flv','user','draft','746337947','99999'
function instance_remotedownload($contextid,$filename,$component, $filearea,$itemid, $requestid){
global $CFG,$USER;
//set up return object	
//set up return object	

$return=fetchReturnArray(true);

	//set up auto transcoding (mp3 or mp4) or not
	//The jsp to call is different.
	$jsp="download.jsp";
	$ext = substr($filename,-4); 
	if($ext ==".mp4" || $ext ==".mp3"){
		$jsp = "convert.jsp";
	}

$red5_fileurl= "http://" . $CFG->filter_poodll_servername . 
						":"  .  $CFG->filter_poodll_serverhttpport . "/poodll/" . $jsp . "?poodllserverid=" . 
						$CFG->filter_poodll_serverid . "&filename=" . $filename . "&caller=" . urlencode($CFG->wwwroot);
					
//	$red5_fileurl= "http://" . $CFG->filter_poodll_servername . 
//						":443/poodll/" . $filename;

						
	//setup our file manipulators
		$fs = get_file_storage();
		$browser = get_file_browser();
		
		$filepath='/';
		
	//create the file record for our new file
		$file_record = array(
		'userid' => $USER->id,
		'contextid'=>$contextid, 
		'component'=>$component, 
		'filearea'=>$filearea,
        'itemid'=>$itemid, 
		'filepath'=>$filepath, 
		'filename'=>$filename,
		'author'=>'moodle user',
		'license'=>'allrighttsreserved',		
		'timecreated'=>time(), 
		'timemodified'=>time()
		);
		
		
		//if file already exists, delete it
		//we could use fileinfo, but it don&'t work
		if($fs->file_exists($contextid,$component,$filearea,$itemid,$filepath,$filename)){
			//delete here ---
		}
		
		//download options
	$options = array();
	$options['headers']=null;
	$options['postdata']=null;
	$options['fullresponse']=false;
	$options['timeout']=300;
	$options['connecttimeout']=20;
	$options['skipcertverify']=false;
	$options['calctimeout']=false;
	
		//clear the output buffer, otherwise strange characters can get in to our file
		//seems to have no effect though ...
		while (ob_get_level()) {
                        ob_end_clean();
                } 

		//actually copy over the file from remote server
		if(!$fs->create_file_from_url($file_record, $red5_fileurl,$options, false)){
		//	echo "boo:" . $red5_fileurl;
			$return['success']=false;
			array_push($return['messages'],"Unable to create file from url." );
		}else{
			// echo "yay:" . $red5_fileurl;
				 //get a file object if successful
				 $thecontext = get_context_instance_by_id($contextid);
				 $fileinfo = $browser->get_file_info($thecontext, $component,$filearea, $itemid, $filepath, $filename);
			
				//if we could get a fileinfo object, return the url of the object
				 if($fileinfo){
						//$returnfilepath  = $fileinfo->get_url();
						$returnfilepath = $filename;
						array_push($return['messages'],$returnfilepath );
				}else{
					//if we couldn't get an url and it is a draft file, guess the URL
					//<p><a href="http://m2.poodll.com/draftfile.php/5/user/draft/875191859/IMG_0594.MOV">IMG_0594.MOV</a></p>
					if($filearea == 'draft'){
						/*
						$returnfilepath= $CFG->wwwroot. "/draftfile.php/" . $contextid . "/" 
								. $component . "/" . $filearea 
								. "/" . $itemid . "/" . $filename;
								*/
						$returnfilepath = $filename;		
						array_push($return['messages'],$returnfilepath );
					}else{
						$return['success']=false;
						array_push($return['messages'],"Unable to get URL for file." );
					}
				}//end of if fileinfo
		}//end of if could create_file_from_url
		

		//we process the result for return to browser
		$xml_output=prepareXMLReturn($return, $requestid);	
		
		//we return to browser the result of our file operation
		return $xml_output;

		
}

function instance_download($mimetype,$filename,$filehash,$requestid){
//paramone=mimetype paramtwo=filename paramthree=filehash requestid, 
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment;filename='" . $filename . "'");
header("Content-Type: " . $mimetype);
header("Content-Transfer-Encoding: binary");
//header('Accept-Ranges: bytes');

			$fs = get_file_storage();
			$f = $fs->get_file_by_hash($filehash);
			if($f){
				//$content = $f->get_content();
				//echo $content;
				$f->readfile();
			}else{
				//set up return object	
				$return=fetchReturnArray(false);
				array_push($return['messages'],"file not found." );
				$xml_output=prepareXMLReturn($return, $requestid);	
				header("Content-type: text/xml");
				echo "<?xml version=\"1.0\"?>\n";
				echo $xml_output;
				return;
			}
}

//This will delete a single file/dir from a module instance
function instance_deletefile($filehash, $requestid){
	$fs = get_file_storage();
	$f = $fs->get_file_by_hash($filehash);
	
	//set up return object	
	$return=fetchReturnArray(true);
	
	
	//if we don't get a file we can out
	if(!$f){
		$return['success']=false;
		array_push($return['messages'],"no such file/dir to delete." );
		//we process the result for return to browser
		$xml_output=prepareXMLReturn($return, $requestid);		   
		return $xml_output;
	}
	
	//call our delete file handling method
	$return = instance_deletefile_internal($f);	
	
	
	//we process the result for return to browser
	$xml_output=prepareXMLReturn($return, $requestid);		   
	return $xml_output;
}

//This will delete a single file/dir from a module instance
function instance_fetchfileinfo($filehash, $requestid){
	$fs = get_file_storage();
	$f = $fs->get_file_by_hash($filehash);
	
	//set up return object	
	$return=fetchReturnArray(true);
	
	
	//if we don't get a file we can out
	if(!$f){
		$return['success']=false;
		array_push($return['messages'],"no such file/dir to delete." );
		//we process the result for return to browser
		$xml_output=prepareXMLReturn($return, $requestid);		   
		return $xml_output;
	}else{
		$return['success']=false;
		array_push($return['messages'], "component:" . $f->get_component() . " filearea:" . $f->get_filearea() . " itemid:" . $f->get_itemid() . " filepath:" . $f->get_filepath() . " filename:" . $f->get_filename());
	
	}
	
	
	//we process the result for return to browser
	$xml_output=prepareXMLReturn($return, $requestid);		   
	return $xml_output;
}


//it is called by instance_delete, and instance_rename/copyas file
//BOGUS BOGUS BOGUS
function bogus_instance_deletefile_internal($f){
	//set up return object	
			$return=fetchReturnArray(false);

			//fetch our info object
			$browser = get_file_browser();
			$thecontext = get_context_instance_by_id($f->get_contextid());
			$fileinfo = $browser->get_file_info($thecontext, $f->get_component(),$f->get_filearea(), $f->get_itemid(), $f->get_filepath(), $f->get_filename());
	
			//if we don't have permission to delete, exit
			if(!$fileinfo || !$fileinfo->is_writable()){
				$return['success']=false;
				//array_push($return['messages'],"You do not have  permissions to delete this file." );
				array_push($return['messages'],'TNO:' . $thecontext->id . " " . $f->get_component() . " " .  $f->get_filearea(). " " .  $f->get_itemid(). " " .  $f->get_filepath(). " " .  $f->get_filename());		
			
			//if it is a directory, head in and do recursive processing	
			}else if($f->is_directory()){
				array_push($return['messages'],'TYES:' . $thecontext->id . " " . $f->get_component() . " " .  $f->get_filearea(). " " .  $f->get_itemid(). " " .  $f->get_filepath(). " " .  $f->get_filename());		
			
			   $sreturn= bogus_instance_deletedircontents($f);
			   $return = mergeReturnArrays($return,$sreturn);
			
			//if it is a single file, just delete it
			}else{
				array_push($return['messages'],'TTYES:' . $thecontext->id . " " . $f->get_component() . " " .  $f->get_filearea(). " " .  $f->get_itemid(). " " .  $f->get_filepath(). " " .  $f->get_filename());		
			
				
			}
			return $return;
}
//This will delete the contents of a directory in a module instance
//it may be called recursively if the dir contains sub dirs
function bogus_instance_deletedircontents($sfdir){
	
	//set up return object	
	$return=fetchReturnArray(false);
	
	//get file handling objects
	//it is unlikely that sub dirs or files have different permissions to their parents
	//so perhaps the permissions checks(filebrowser) are unnecessary. but 
	 $fs = get_file_storage();
	 $browser = get_file_browser();
	 
	 
	if($sfdir->is_directory()){
		$files = $fs->get_directory_files( $sfdir->get_contextid(), 
										 $sfdir->get_component(),
										 $sfdir->get_filearea(),
										 $sfdir->get_itemid(), 
										 $sfdir->get_filepath(), 
										 false,true);
		
		foreach($files as $f){
		
			$thecontext = get_context_instance_by_id($f->get_contextid());
			$fileinfo = $browser->get_file_info($thecontext, $f->get_component(),$f->get_filearea(), $f->get_itemid(), $f->get_filepath(), $f->get_filename());
			//if we have insuff permissions to delete. Exit.
			//if(!$fileinfo){
			if(!$fileinfo || !$fileinfo->is_writable()){
				array_push($return['messages'],' SNO:' . $thecontext->id . " " . $f->get_component() . " " .  $f->get_filearea(). " " .  $f->get_itemid(). " " .  $f->get_filepath(). " " .  $f->get_filename());		
			
			}else if(!$fileinfo->is_writable()){
				array_push($return['messages'],'SSNO:' . $thecontext->id . " " . $f->get_component() . " " .  $f->get_filearea(). " " .  $f->get_itemid(). " " .  $f->get_filepath(). " " .  $f->get_filename());		
			
			}else{	
				if(!$f->is_directory()){
					array_push($return['messages'],'SYES:' . $thecontext->id . " " . $f->get_component() . " " .  $f->get_filearea(). " " .  $f->get_itemid(). " " .  $f->get_filepath(). " " .  $f->get_filename());		
					if(!$fileinfo->delete()){				
						$return['success']=false;
						array_push($return['messages'],"unable to delete" . $f->get_filepath() . " "  . $f->get_filename());
					}
				}else{
					array_push($return['messages'],'SSYES:' . $thecontext->id . " " . $f->get_component() . " " .  $f->get_filearea(). " " .  $f->get_itemid(). " " .  $f->get_filepath(). " " .  $f->get_filename());		
					 $sreturn= bogus_instance_deletedircontents($f);
					$return = mergeReturnArrays($return,$sreturn);
				}
			}//end of is deletable
			
		}//end of for each
		
		
	//if it is not a directory complain
	}else{
			$return['success']=false;
			array_push($return['messages'],"unable to delete non dir: " . $singlefile->get_filepath() . $singlefile->get_filename());
	}
	
	return $return;
}

//This will delete a file or directory(by calling a recursive function), 
//it is called by instance_delete, and instance_rename/copyas file
function instance_deletefile_internal($f){

			//set up return object	
			$return=fetchReturnArray(true);

			//fetch our info object
			$browser = get_file_browser();
			$thecontext = get_context_instance_by_id($f->get_contextid());
			$fileinfo = $browser->get_file_info($thecontext, $f->get_component(),$f->get_filearea(), $f->get_itemid(), $f->get_filepath(), $f->get_filename());
	
			//if we don't have permission to delete, or the file cant be info'd exit
			if(!$fileinfo || !$fileinfo->is_writable()){
				$return['success']=false;
				array_push($return['messages'],"You do not have  permissions to delete this file." );
				//array_push($return['messages'],$thecontext->id . " " . $f->get_component() . " " .  $f->get_filearea(). " " .  $f->get_itemid(). " " .  $f->get_filepath(). " " .  $f->get_filename());		
			
			//if it is a directory, head in and do recursive processing	
			}else if($f->is_directory()){
			   $sreturn= instance_deletedircontents($f);
			   $return = mergeReturnArrays($return,$sreturn);
			
			//if it is a single file, just delete it
			}else{
				//array_push( $return['messages'], "DELOK" . $thecontext->id . ':' . $f->get_component() . ':' . $f->get_filearea() . ':' . $f->get_itemid()  . ':' . $f->get_filepath() . ':' . $f->get_filename());

				if($fileinfo->delete()){
					$return['success']=true;	
				}
			}
			return $return;
}

//This will delete the contents of a directory in a module instance
//it may be called recursively if the dir contains sub dirs
function instance_deletedircontents($sfdir){
	
	//set up return object	
	$return=fetchReturnArray(true);
	
	//get file handling objects
	//it is unlikely that sub dirs or files have different permissions to their parents
	//so perhaps the permissions checks(filebrowser) are unnecessary. but 
	 $fs = get_file_storage();
	 $browser = get_file_browser();
	 
	 
	if($sfdir->is_directory()){
		$files = $fs->get_directory_files( $sfdir->get_contextid(), 
										 $sfdir->get_component(),
										 $sfdir->get_filearea(),
										 $sfdir->get_itemid(), 
										 $sfdir->get_filepath(), 
										 false,true);
		
		foreach($files as $singlefile){
		
			$thecontext = get_context_instance_by_id($singlefile->get_contextid());
			$fileinfo = $browser->get_file_info($thecontext, $singlefile->get_component(),$singlefile->get_filearea(), $singlefile->get_itemid(), $singlefile->get_filepath(), $singlefile->get_filename());
			
			//if the file cant be info'd, exit.
			if(!$fileinfo){
				$return['success']=false;
				array_push($return['messages'],"couldnt get fileinfo " . $singlefile->get_filepath() . ": :"  . $singlefile->get_filename());
			
			//if we have insuff. permissions, fail
			}else if(!$fileinfo->is_writable()){
		
				$return['success']=false;
				array_push($return['messages'],"You do not have adequate permissions to delete " . $singlefile->get_filepath() . " "  . $singlefile->get_filename());
		
			//attempt the delete or recursive delete if dir
			}else{	
				if(!$singlefile->is_directory()){
					if(!$fileinfo->delete()){				
						$return['success']=false;
						array_push($return['messages'],"unable to delete" . $singlefile->get_filepath() . " "  . $singlefile->get_filename());
					}
				}else{
					$sreturn = instance_deletedircontents($singlefile);
					$return = mergeReturnArrays($return,$sreturn);
				}
			}//end of is deletable
			
		}//end of for each
		
		//if we could delete all subfiles and dirs, then we can delete this dir itself.
		$files = $fs->get_directory_files( $sfdir->get_contextid(), 
									 $sfdir->get_component(),
									 $sfdir->get_filearea(),
									 $sfdir->get_itemid(), 
									 $sfdir->get_filepath(), 
									 true,true);
		if(!($files && $files.length >0)){
			$sfdir->delete();
		}	
		
	//if it is not a directory complain, single files shouldn't be passed in to this method
	}else{
			$return['success']=false;
			array_push($return['messages'],"unable to delete non dir: " . $singlefile->get_filepath() . $singlefile->get_filename());
	}
	
	return $return;
}


//This creates an empty dir in 
//available in a module instance (ie added from repository)
function instance_createdir($moduleid, $courseid, $itemid, $filearea, $newdir, $requestid){

	if(pathIsWritable($moduleid, $courseid, $itemid, $filearea,"/","")){
		$return = do_createdir($moduleid, $courseid, $itemid, $filearea, $newdir);
	}else{
		//set up return object	
		$return=fetchReturnArray(false);
		 $return['success']=false;
	  	 array_push($return['messages'],"insuffficient permissions to create dir: " . $newdir );
	}
	$xml_return = prepareXMLReturn($return,$requestid);
	return $xml_return;
}

function do_createdir($moduleid, $courseid, $itemid, $filearea, $newdir){
		global $CFG, $DB;

	//FIlter could submit submission/draft/content/intro as options here
	if($filearea == "") {$filearea ="content";}
	
	//fetch info and ids about the module calling this data
	$course = $DB->get_record('course', array('id'=>$courseid));
	$modinfo = get_fast_modinfo($course);
	$cm = $modinfo->get_cm($moduleid);
	$component = "mod_" . $cm->modname;
	
	//get a handle on the module context
	$thiscontext = get_context_instance(CONTEXT_MODULE,$moduleid);
	$contextid = $thiscontext->id;

	//get filehandling objects
	$browser = get_file_browser();
	$fs = get_file_storage();

	
	//set up return object	
	$return=fetchReturnArray(true);
	
	//Must begin and end with slash
	if($newdir != ''){
		if (strpos($newdir, '/') !== 0){
			$newdir= '/' . $newdir;
		}
		if (strrpos($newdir , '/') !== strlen($newdir)-1){
			$newdir= $newdir . '/' ;
		}
	}else{
		$newdir= '/' ;
	}
	
	//check if file already exists, if so can out
	if($fs->file_exists($contextid,$component,$filearea,$itemid,$newdir,".")){
		//set up return object	
		$return['success']=false;
		array_push($return['messages'],$newdir . " :already exists here.");
		
		
		//for some reason this always returns false.	
	}else if($fs->create_directory($contextid, $component, $filearea, $itemid, $newdir)){
		$return['success']=true;
	
	}else{
	   $return['success']=false;
	   array_push($return['messages'],"unable to create dir: " . $newdir );
	
	}
		   
	return $return;	

}

//Returns boolean true if file at passed in path exists.
function instance_exists($pathname){
	return file_exists_by_hash($pathname);
}

//Copies over a single file from rep to module instance
//workhorse function, is called internally
function do_copyfilein($moduleid, $courseid, $itemid, $filearea, $filepath,$newpath, $requestid){
	global $CFG, $DB;


	//new return values array
	$return = fetchReturnArray(false);
	
	//FIlter could submit submission/draft/content/intro as options here
	if($filearea == "") {$filearea ="content";}
	
	//fetch info and ids about the module calling this data
	$course = $DB->get_record('course', array('id'=>$courseid));
	$modinfo = get_fast_modinfo($course);
	$cm = $modinfo->get_cm($moduleid);
	$component = "mod_" . $cm->modname;
	
	//get a handle on the module context
	$thiscontext = get_context_instance(CONTEXT_MODULE,$moduleid);
	$contextid = $thiscontext->id;
	
	//get filehandling objects
	$browser = get_file_browser();
	$fs = get_file_storage();

	
	//Make full path to source file
	$filepath = $CFG->{'dataroot'} . $filepath;
	
	//Make full"virtual path" as new path
	if($newpath != ''){
		if (strpos($newpath, '/') !== 0){
			$newpath= '/' . $newpath;
		}
		if (strrpos($newpath , '/') !== strlen($newpath)-1){
			$newpath= $newpath . '/' ;
		}
		//$newpath= '/' . $newpath . '/';
	}else{
		$newpath= '/' ;
	}
	
	//Make filename
	//basename dont work well for multibyte unless locale set so try the explode function(maybe unic dependant though)
	//$filename=basename($filepath);
	$filename = poodllBasename($filepath);
	//$filename="hello";

	//check if file already exists, if so can out
	if($fs->file_exists($contextid,$component,$filearea,$itemid,$newpath,$filename)){
		$return['success'] = false;
		array_push($return['messages'],$filename . " already exists at " . $newpath);
		
		//Return the data
		return $return;
	}
	
	//new filearray
	$newfile = array();
	$newfile['contextid'] = $contextid;
	$newfile['component'] = $component;
	$newfile['filearea'] = $filearea;
	$newfile['itemid'] = $itemid;
	$newfile['filepath'] = $newpath; // I guess change here for subdirs, begin slash, trail slash
	$newfile['sortorder'] = "0";
	$newfile['filename'] = $filename;
	
	
	//set up xml to return	
	$xml_output = "<result requestid='" . $requestid . "'>";
	
	if($fs->create_file_from_pathname($newfile, $filepath)){
	//if(false){
		
		$return['success'] = true;
		
	//	$return['success'] = false;
	//	array_push($return['messages'], $newpath . "  " . $filepath);
		
		return $return;
	}else{
		$return['success'] = false;
		array_push($return['messages'],"Unable to create " . $filename . " at " . $newpath);
		//array_push($return['messages'],"newfilename:" . $newfile['filename']);
		//array_push($return['messages'],"filepath:" . $newfile['filepath']);
		//array_push($return['messages'],"itemid:" . $newfile['itemid']);
		return $return;
	}
	
}


//Copy a single file into an instance file area
function instance_copyfilein($moduleid, $courseid, $itemid, $filearea, $filepath,$newpath, $requestid){
	global $CFG, $DB;
	
	//do the copying and fetch back the result
	//$filepath="/repository/audiofiles/adir/jackquizimages/iconfour.png";
	$return = do_copyfilein($moduleid, $courseid, $itemid, $filearea, $filepath,$newpath, $requestid);
							
	$xml_output = prepareXMLReturn($return, $requestid);

	//Return the data
	return $xml_output;
	
}




//Fetch a sub directory list for file explorer  
//calls itself recursively
function instance_copydircontents($moduleid, $courseid, $itemid, $filearea, $dir,$newpath, $requestid,  $recursive=false){
	global $CFG;
	
	//new return values array
	$dirreturn = fetchReturnArray(true);
	
	$fullpath = $CFG->{'dataroot'}  . $dir; 
	$files = scandir($fullpath);
	if (!empty($files)) {
        foreach ($files as $afile) {
			if ($afile == "." || $afile == "..") {
				continue;
			}
			
			//differntiate between copying file and copying subdir
			if(is_dir($fullpath."/".$afile) && $recursive){
				//$subsubreturn = do_createdir($moduleid, $courseid, $filearea, $newdir);
				$subreturn =  instance_copydircontents($moduleid, $courseid, $itemid, $filearea, $dir."/".$afile ,$newpath . "/" . $afile, $requestid,  $recursive);
			}else{
				$subreturn = do_copyfilein($moduleid, $courseid, $itemid, $filearea, $dir."/". $afile,$newpath, $requestid);
			}
			
			//process return values
			if(!$subreturn['success']){
				$dirreturn = mergeReturnArrays($dirreturn,$subreturn);
			}//end of process returns
		}//end of for each file
	}//end of if empty files

	return $dirreturn;
}


//Copy an entire directory from rep over to module instance
function instance_copydirin($moduleid, $courseid, $itemid, $filearea, $filepath,$newpath, $requestid){
	global $USER, $CFG;	
	
	
	global $basedir;
    global $usecheckboxes;
    global $id;
    
	
	//Handle directories
	$fullpath = $CFG->{'dataroot'}  . $filepath;
	
	//prepare return array
	$return=fetchReturnArray(false);
	
	$files = scandir($fullpath);
	
	//if no files to copy throw error
	if (empty($files)) {
		array_push($return['messages'],"no files in directory to copy.");
		
	}else{
		//if area writeable proceed, else throw error
		if(pathIsWritable($moduleid, $courseid, $itemid, $filearea,"/","")){
			$return = instance_copydircontents($moduleid, $courseid, $itemid, $filearea, $filepath,$newpath, $requestid,true);
		
		}else{
			$return['success']=false;
			array_push($return['messages'],"you do not have permission to write in this directory.");
		
		}
	}//end of if empty files 
	
	
	//Return the data
	$xml_output = prepareXMLReturn($return,$requestid);
	//$xml_output = "<result>I love you</result>";
	return $xml_output;
}

function instance_duplicatefile($moduleid, $courseid, $itemid, $filearea, $filepath, $originalhash, $requestid){
	
	//set up return object	
	$return=fetchReturnArray(true);
	
	//get filehandling objects
	$browser = get_file_browser();
	$fs = get_file_storage();
	
	//get file to copy 
	$f = $fs->get_file_by_hash($originalhash);
	
	if(!$f){
		$return['success']=false;
		array_push($return['messages'],"Unable to fetch original file. ");
	}else{
		//kick off the recursive thing
		$return = instance_duplicatefilecontents($f, $moduleid, $courseid, $itemid, $filearea, $filepath , $requestid);
	}
	
	//Return the data
	$xml_output = prepareXMLReturn($return,$requestid);
	//$xml_output = "<result>I love you</result>";
	return $xml_output;

}


function instance_duplicatefilecontents($f, $moduleid, $courseid, $itemid, $filearea, $filepath , $requestid, $filename=''){
	global $CFG, $DB;

	//new return values array
	$return = fetchReturnArray(true);
	
	//get filehandling objects
	$browser = get_file_browser();
	$fs = get_file_storage();
	
	//get file to copy 
	if(!$f){
		$return['success']=false;
		array_push($return['messages'],"Unable to fetch original file. ");
		return $return;
	}
	
	//Filter could submit submission/draft/content/intro as options here
	if($filearea == "") {$filearea ="content";}
	
	//fetch info and ids about the module to which we will duplicate our file.
	$course = $DB->get_record('course', array('id'=>$courseid));
	$modinfo = get_fast_modinfo($course);
	$cm = $modinfo->get_cm($moduleid);
	$component = "mod_" . $cm->modname;
	
	//get a handle on the module context
	$thiscontext = get_context_instance(CONTEXT_MODULE,$moduleid);
	$contextid = $thiscontext->id;
	
	
	//use the original filename , as the new name if we have not been given a name to use
	
	//$filepath=$f->get_filepath();
	
	if ($f->is_directory()){
	
		
		$files = $fs->get_directory_files( $f->get_contextid(), 
										 $f->get_component(),
										 $f->get_filearea(),
										 $f->get_itemid(), 
										 $f->get_filepath(), 
										 true,true);
		
		//get the dir name	if one has not been passed in
		if($filename==''){
			$dirname=poodllBasename($f->get_filepath());
			
		}else{
			//here we need to get logic
			//e.g /home/villages should go to /home/smalltown but it is going to /home/villages/smalltown
			//so we need to get the parent directory (what if root?)
			$filepath = $f->get_parent_directory()->get_filepath();
			$dirname=$filename;
		}
		
		//add the new dir name to the filepath to copy to								 
		$filepath = $filepath . $dirname  .  DIRECTORY_SEPARATOR;
			
	
		
		
		//call on the copy logic for each file
		foreach($files as $singlefile){
			
			$subreturn = instance_duplicatefilecontents($singlefile,$moduleid, $courseid,$itemid, $filearea, $filepath , $requestid);
				//process return values
			if(!$subreturn['success']){
				$return = mergeReturnArrays($return,$subreturn);
			}//end of process returns
		}//end of for each
	
	
	
		
	
	}else{
	
		//autogenerate a filename if one has not been passed in
		if($filename==''){
			$filename=$f->get_filename();
		}
		
		//fetch the file info object for our original file
		$original_context = get_context_instance_by_id($f->get_contextid());
		$original_fileinfo = $browser->get_file_info($original_context, $f->get_component(),$f->get_filearea(), $f->get_itemid(), $f->get_filepath(), $f->get_filename());
	
		//perform the copy	
		if($original_fileinfo){
			$return['success'] = $original_fileinfo->copy_to_storage($contextid, $component, $filearea, $itemid, $filepath, $filename);
			//$return['success'] =false;
			
		}//end of if $original_fileinfo
	}

	//add a message if we could not do the action
	if(!$return['success']){
		array_push($return['messages'],"unable to copy file to: " . $filepath . $filename);
	}

	//Return the data
	return $return;

}

//here we rename a file or directory
function instance_renamefile($moduleid, $courseid, $originalhash,$newfilename, $copyas, $requestid){
	//set up return object	
	$return=fetchReturnArray(true);
	
	//get filehandling objects
	$browser = get_file_browser();
	$fs = get_file_storage();
	
	//get file to copy 
	$f = $fs->get_file_by_hash($originalhash);
	
	//get oldfilename
	if($f){
		if($f->is_directory()) {
			$oldfilename=poodllBasename($f->get_filepath());
		}else{
			$oldfilename=$f->get_filename();
		}
	}else{
		$oldfilename="";
	}
	
	if(!$f){
		$return['success']=false;
		array_push($return['messages'],"Unable to fetch original file: " . $originalhash);
	//check if the file we wish to copy to already exists, and that the new filename is diff to old one
	}else if( $newfilename == $oldfilename){
		$return['success']=false;
		array_push($return['messages'],"can't rename a file with its original name.");
		
	}else if($fs->file_exists($f->get_contextid(),$f->get_component(),$f->get_filearea(),$f->get_itemid(),$f->get_filepath(),$newfilename)){
		$return['success']=false;
		array_push($return['messages'],"A file with that name already exists in the current directory.");
	
	}else {
		//kick off the recursive copy thing
		$return = instance_duplicatefilecontents($f, $moduleid, $courseid, $f->get_itemid(), $f->get_filearea(), $f->get_filepath() , $requestid, $newfilename);
	}
	
	//if we were successful, and were renaming, delete the original
	if($return['success']){
		if(!$copyas){
			$return = instance_deletefile_internal($f);
		}
	
	//if we were not successful, and renaming, add an error
	}else{
		if(!$copyas){
			array_push($return['messages'],"Because of errors, original file(s) not deleted ");
		}
	}
	
	//Return the data
	$xml_output = prepareXMLReturn($return,$requestid);
	//$xml_output = "<result>I love you</result>";
	return $xml_output;

}

function xinstance_renamefile($moduleid, $courseid, $itemid, $filearea,  $filepath,$newfilename, $copyas, $requestid){
	global $CFG, $DB;

	//new return values array
	$return = fetchReturnArray(false);
	
	
	//FIlter could submit submission/draft/content/intro as options here
	if($filearea == "") {$filearea ="content";}
	
	//fetch info and ids about the module calling this data
	$course = $DB->get_record('course', array('id'=>$courseid));
	$modinfo = get_fast_modinfo($course);
	$cm = $modinfo->get_cm($moduleid);
	$component = "mod_" . $cm->modname;
	
	//get a handle on the module context
	$thiscontext = get_context_instance(CONTEXT_MODULE,$moduleid);
	$contextid = $thiscontext->id;
	

	//establish our filename and filepath
	$filename=poodllBasename($filepath);
	//There is probably a better way to do this, that doesnt hang on multipbyte
	//need to remove filename and leave trailing dir sep. 
	//perhaps we should have sent it from widget to here with preceding slash? This could get confusing ..
	$filepath=DIRECTORY_SEPARATOR . strrev(strstr(strrev($filepath),DIRECTORY_SEPARATOR));
	
	
	
	//get filehandling objects
	$browser = get_file_browser();
	$fs = get_file_storage();
	$f = $fs->get_file($contextid,$component,$filearea,$itemid,$filepath,$filename) ;
	
	//get file fails if it is directory (i think its a bug ..check latest moodle version)
	//if($f && $f->is_directory()) {
	if(!$f){
		$return['success']=false;
		array_push($return['messages'],"Directories cannot be copied or renamed(yet). Sorry, next version.");
	
	//check if the file we wish to copy to already exists, and that the new filename is diff to old one
	}else if( $newfilename == $filename){
		$return['success']=false;
		array_push($return['messages'],"can't rename a file with its original name.");
		
	}else if($fs->file_exists($contextid,$component,$filearea,$itemid,$filepath,$newfilename)){
		$return['success']=false;
		array_push($return['messages'],"A file with that name already exists in the current directory.");
	

	
	//commence the copy and delete
	}else{
		//fetch our info object
		$fileinfo = $browser->get_file_info($thiscontext, $component,$filearea, $itemid, $filepath, $filename);
		if($fileinfo && $fileinfo->is_writable()){
			$return['success'] = $fileinfo->copy_to_storage($contextid, $component, $filearea, $itemid, $filepath, $newfilename);
			//if we could copy ok, lets delete the original file
			if($return['success']){
			
					if($copyas || $fileinfo ->delete()){
						$return['success']=true;	
					}else{
						$return['success']=false;
						array_push($return['messages'],"copied but unable to delete original file." );
					}
			
			}
		}else{
			$return['success']=false;
			array_push($return['messages'],"unable to fetch original file. Are you logged in?");
			//array_push($return['messages'],$thiscontext->id . " " . $component . " " .  $filearea . " " .  $itemid . " " .  $filepath . " " .  $filename);
		}
	}


	
	
	if(!$return['success']){
		$return['success']=false;
		array_push($return['messages'],"unable to rename/copy file");
	}

	//Return the data
	$xml_output = prepareXMLReturn($return,$requestid);
	return $xml_output;

}


//this initialises and returns a results array
//But I think it may misguided, because we need more info at use time
//than is available to be passed in
//function fetchRealUrl($moduleid, $courseid, $filearea, $filepath, $requestid){
function fetchRealUrl($moduleid,$courseid, $itemid, $filearea, $filepath, $requestid){
	global $PAGE, $DB;
	
	//new return values array
	$return = fetchReturnArray(false);
	
	
	//fetch info and ids about the module calling this data
	$course = $DB->get_record('course', array('id'=>$courseid));
	$modinfo = get_fast_modinfo($course);
	
	//get component info
	//may be able to avoid useing moduleid, by using PAGE global
	$cm = $modinfo->get_cm($moduleid);
	//$cm=$PAGE->cm;
	$component = "mod_" . $cm->modname;
	
	//get module context
	//may be able to avoid useing moduleid, by using PAGE global
	$thecontext = get_context_instance(CONTEXT_MODULE,$moduleid);
	//$thecontext=$PAGE->context;

	
	
	
	//FIlter could submit submission/draft/content/intro as options here
	if($filearea == "") {$filearea ="content";}
	
	
	//establish our filename
	$filename=poodllBasename($filepath);
	//There is probably a better way to do this, that doesnt hang on multipbyte
	//need to remove filename and leave trailing dir sep
	$filepath=strrev(strstr(strrev($filepath),DIRECTORY_SEPARATOR));
	
	
	//get the file brower object
	$browser = get_file_browser();
			
					
	//fetch our info object
	$fileinfo = $browser->get_file_info($thecontext, $component,$filearea, $itemid, $filepath, $filename);
			
	//get the url to the file
	if($fileinfo){
			$urltofile = $fileinfo->get_url();
	}else{
			$urltofile = "accessdenied";
	}

	//prepare our return array
	$return['success']=false;
	array_push($return['messages'],"we have a url");
	array_push($return['messages'],$filepath . " " . $filename);
	//array_push($return['messages'],$thecontext->id . " " . $component . " " .  $filearea . " " .  $itemid . " " .  $filepath . " " .  $filename);
	array_push($return['messages'],$urltofile);

	//Return the data
	$xml_output = prepareXMLReturn($return,$requestid);
	return $xml_output;


}

function getmoddata($courseid,$requestid){
	global $DB;
	
	
	
	//fetch info and ids about the modules in this course
	$course = $DB->get_record('course', array('id'=>$courseid));
 	$modinfo =& get_fast_modinfo($course);   
    get_all_mods($courseid, $mods, $modnames, $modnamesplural, $modnamesused);
    $sections = get_all_sections($courseid);
     /* Displays the type of mod name - assignment/ quiz etc 
    foreach($modnames as $modname) {
	   array_push($return['messages'],$modname);
    }
    */
    
    $sectionarray = array();
    foreach($sections as $section){
    	
    	//$sectionarray[$section->id] = get_section_name($course,$section);
    	//here we will store all the mods for the section
    	$sectionarray[$section->section] = array();
    	
    }
    
    //for each mod add its name and id to an array for its section
    foreach($mods as $mod) {
    		//$modname = htmlspecialchars($modinfo->cms[$mod->id]->name, ENT_QUOTES);
    		$modname = htmlspecialchars($mod->name, ENT_QUOTES);
    		$modtype = $mod->modfullname;
    		$sectionid=$modinfo->cms[$mod->id]->sectionnum;
    		array_push($sectionarray[$sectionid], "<module sectionid='" . $sectionid . "' modid='" . $mod->id .  "' modname='" . $modname. "'  modtype='" . $modtype . "'  />");
    }
    
    //init xml output
  	$xml_output = "<course courseid='" . $courseid . "'>";
   
   //go through each section adding a sect header and all the modules in it
   foreach($sections as $section){
    	
    	//$sectionarray[$section->id] = get_section_name($course,$section);
    	//here we will store all the mods for the section
    	$sectionname =  htmlspecialchars(get_section_name($course,$section),ENT_QUOTES);
    	$xml_output .= "<section sectionid='" . $section->section . "' sectionname='" . $sectionname ."'>"; 
    	foreach($sectionarray[$section->section]  as $line){
    		$xml_output .= "\t" . $line;
    	}
    	$xml_output .= "</section>";
    }

   //close off xml output
    $xml_output .= "</course>";
   
    //"section", "section, id, course, name, summary, summaryformat, sequence, visible");

	//Return the data
	//$xml_output = prepareXMLReturn($return,$requestid);
	return $xml_output;
}

function getLast20Files(){
global $DB;
	$sql = "select * from {files} order by id desc limit 20;";
	 
   $records=$DB->get_records_sql($sql);
   if (!empty($records)) {
		
		foreach ($records as $record){
		
			print_object($record);
		}
		
	}
}

//this turns our results array into an xml string for returning to browser
function prepareXMLReturn($resultArray, $requestid){
	//set up xml to return	
	$xml_output = "<result requestid='" . $requestid . "'>";

		if($resultArray['success']){
			$xml_output .= 'success';
			//not sure how this will impact attachment explorer .. (expects no messages here, but recorder expects..)
			foreach ($resultArray['messages'] as $message) {
				$xml_output .= '<error>' . $message . '</error>';
			}
		}else{
			$xml_output .= 'failure';
			foreach ($resultArray['messages'] as $message) {
				$xml_output .= '<error>' . $message . '</error>';
			}
		}
	
	
	//close off xml to return	
	$xml_output .= "</result>";	
	return $xml_output;
}


//this merges two result arrays, mostly for use with actions across recursive directories.
function mergeReturnArrays($return1,$return2){
	$return1['success'] = $return1['success'] && $return2['success']; 
	//process return values
	if(!$return1['success'] && !$return2['success']){
		foreach ($return2['messages'] as $message) {
			array_push($return1['messages'],$message);
		}
	}
	return $return1;
}

//this initialises and returns a results array
function fetchReturnArray($initsuccess=false){
	//new filearray
	$return = array();
	$return['messages'] = array();
	$return['success'] = $initsuccess;
	return $return;
}

//The basename function is unreliable with multibyte strings
//This is a cobbled together, dodgey alternative
function poodllBasename($filepath){
		//return basename($filepath,'/');
	//if it is a directory then we should remove the trailing slash because it will
	//get exploded into an empty string
	if(substr($filepath,-1)==DIRECTORY_SEPARATOR){
		$filepath = substr($filepath,0,-1);
	}
	return end(explode(DIRECTORY_SEPARATOR,$filepath));
	
}

//This is a convenience function for checking that a storedfile is writeable
//
function fileIsWritable($f){
	//get the file brower object
	
	$browser = get_file_browser();
	$thecontext = get_context_instance_by_id($f->get_contextid());
	$fileinfo = $browser->get_file_info($thecontext, $f->get_component(),$f->get_filearea(), $f->get_itemid(), $f->get_filepath(), $f->get_filename());
	//if we have insuff permissions to delete. Exit.
	if(!$fileinfo || !$fileinfo->is_writable()){
		return false;
	}else{
		return true;
	}
}

//This is a convenience function for checking that a storedfile is readable
//
function fileIsReadable($f){
	//get the file brower object
	$browser = get_file_browser();
	$thecontext = get_context_instance_by_id($f->get_contextid());
	$fileinfo = $browser->get_file_info($thecontext, $f->get_component(),$f->get_filearea(), $f->get_itemid(), $f->get_filepath(), $f->get_filename());
	//if we have insuff permissions to delete. Exit.
	if(!$fileinfo || !$fileinfo->is_readable()){
		return false;
	}else{
		return true;
	}
}


//This tells us if the path can be written to
//dirs should have a trailing slash and root is / . if dir, filename should be blank
function pathIsWritable($moduleid, $courseid, $itemid, $filearea,$filepath=DIRECTORY_SEPARATOR,$filename=""){
	global $DB;


	//get a handle on the module context
	$thiscontext = get_context_instance(CONTEXT_MODULE,$moduleid);
	
	//fetch info and ids about the module calling this data
	$course = $DB->get_record('course', array('id'=>$courseid));
	$modinfo = get_fast_modinfo($course);
	$cm = $modinfo->get_cm($moduleid);
	$component = "mod_" . $cm->modname;
	
	//FIlter could submit submission/draft/content/intro as options here
	if($filearea == "") {$filearea ="content";}

	
	//get our file object
	$filepath=DIRECTORY_SEPARATOR;
	$filename="";
	$browser = get_file_browser();
	$fileinfo = $browser->get_file_info($thiscontext, $component,$filearea, $itemid, $filepath, $filename);
	
	//return writeable or not
	if($fileinfo && $fileinfo->is_writable()){
		return true;
	}else{
		return false;
	}
}


//This is used to sort an array of filenames alphabetically
function compareFilenames($a, $b)
{
    return strcasecmp($a->get_filename(), $b->get_filename());
}

//This is used to sort an array of directory names alphabetically
function compareDirnames($a, $b)
{
    return strcasecmp(poodllBasename($a['dirfile']->get_filepath()), poodllBasename($b['dirfile']->get_filepath()));
}